package com.winchain.chainbill.bill.biz.discount.service.impl;

import com.shell.bee.base.exception.UnCheckMsgException;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.entity.auth.AuthOrgan;
import com.shell.bee.persistence.transaction.Transaction;
import com.shell.bee.persistence.transaction.TransactionUtil;
import com.shell.framework.utils.CommonDataUtil;
import com.shell.framework.utils.SysDateUtil;
import com.winchain.chainbill.basic.charge.rx.ValRetBizSaveSubscriber;
import com.winchain.chainbill.basic.invoice.rx.BillInvoiceDeferedUploadMsgSubcriber;
import com.winchain.chainbill.basic.invoice.rx.BillInvoiceDfrUploadSaveSubscriber;
import com.winchain.chainbill.basic.invoice.rx.BillInvoiceDfrUploadUpdateSubscriber;
import com.winchain.chainbill.bill.base.po.CbDct;
import com.winchain.chainbill.bill.base.po.CbOpt;
import com.winchain.chainbill.bill.base.po.CbRec;
import com.winchain.chainbill.bill.base.service.CbDctService;
import com.winchain.chainbill.bill.base.service.CbRecService;
import com.winchain.chainbill.bill.biz.Bill;
import com.winchain.chainbill.bill.biz.BillEvent;
import com.winchain.chainbill.bill.biz.contract.rx.ContractSponsorSubscriber;
import com.winchain.chainbill.bill.biz.discount.rx.BillDctChdSubscriber;
import com.winchain.chainbill.bill.biz.discount.rx.BillDctCpnSubscriber;
import com.winchain.chainbill.bill.biz.discount.rx.BillDctMsgSubscriber;
import com.winchain.chainbill.bill.biz.discount.rx.BillDctPrntSubscriber;
import com.winchain.chainbill.bill.biz.discount.rx.BillDctQtSubscriber;
import com.winchain.chainbill.bill.biz.discount.rx.BillDctSubscriber;
import com.winchain.chainbill.bill.biz.discount.rx.BillSeeFeeContractSponsorSubscriber;
import com.winchain.chainbill.bill.biz.discount.rx.BillSplitDctMsgSubscriber;
import com.winchain.chainbill.bill.biz.discount.service.BillDctRevService;
import com.winchain.chainbill.bill.biz.discount.service.BillDctService;
import com.winchain.chainbill.bill.biz.send.rx.BillAttSubscriber;
import com.winchain.chainbill.bill.biz.send.rx.BillMoveSubscriber;
import com.winchain.chainbill.bill.biz.send.rx.BillOptSubscriber;
import com.winchain.chainbill.bill.biz.send.service.BillCheckService;
import com.winchain.chainbill.bill.biz.send.service.BillService;
import com.winchain.chainbill.bill.biz.send.vo.BatchBillStats;
import com.winchain.chainbill.bill.biz.transfer.vo.BillSplitEvent;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import rx.Observable;

@Service("billDctService")
public class BillDctServiceImpl implements BillDctService {
	@Autowired
	private CbDctService cbDctService;
	@Autowired
	private CbRecService cbRecService;
	@Autowired
	private BillService billService;
	@Autowired
	private BillMoveSubscriber billMoveSubscriber;
	@Autowired
	private BillOptSubscriber billOptSubscriber;
	@Autowired
	private BillDctSubscriber billDctSubscriber;
	@Autowired
	private BillDctPrntSubscriber billDctPrntSubscriber;
	@Autowired
	private BillDctChdSubscriber billDctChdSubscriber;
	@Autowired
	private BillCheckService billCheckService;
	@Autowired
	private BillDctMsgSubscriber billDctMsgSubscriber;
	@Autowired
	private BillSplitDctMsgSubscriber billSplitDctMsgSubscriber;
	@Autowired
	private ContractSponsorSubscriber<CbDct> contractSponsorSubscriber;
	@Autowired
	private BillDctRevService billDctRevService;
	@Autowired
	private BillDctQtSubscriber billDctQtSubscriber;
	@Autowired
	private BillDctCpnSubscriber billDctCpnSubscriber;
	@Autowired
	private ValRetBizSaveSubscriber valRetBizSaveSubscriber;
	@Autowired
	private BillAttSubscriber billAttSubscriber;
	@Autowired
	private BillSeeFeeContractSponsorSubscriber billSeeFeeContractSponsorSubscriber;
	@Autowired
	private BillInvoiceDfrUploadSaveSubscriber billInvoiceDfrUploadSaveSubscriber;
	@Autowired
	private BillInvoiceDfrUploadUpdateSubscriber billInvoiceDfrUploadUpdateSubscriber;
	@Autowired
	private BillInvoiceDeferedUploadMsgSubcriber billInvoiceDeferedUploadMsgSubcriber;

	public String dct(final String billId, final String phoneCode, final String location, final CbDct dct,
			final String attInvoicesJson) {
		final String cusType = CommonDataUtil.getCurEnt().getCusType();

		TransactionUtil.execute(new Transaction() {
			public void doInTransaction() {
				CbRec record = (CbRec) BillDctServiceImpl.this.cbRecService.selectByKey(billId);
				String msg = BillDctServiceImpl.this.billCheckService.checkBillDct(record, dct);
				if (StringUtil.notEmpty(msg)) {
					throw new UnCheckMsgException(msg);
				}
				List<Bill<CbDct>> bills = BillDctServiceImpl.this.billService.init(record, new CbDct[] { dct });

				int size = bills.size();
				if (size == 1) {
					BillDctServiceImpl.this.dct((Bill) bills.get(0), attInvoicesJson, dct.getContractFileIds());
				} else if (size > 1) {
					BillDctServiceImpl.this.splitDct(record, bills, attInvoicesJson, dct.getContractFileIds());
				}
				if (("PERSONAL".equals(cusType)) || ("SELF_EMPLOYED".equals(cusType))) {
					BatchBillStats<CbDct> stats = BillDctServiceImpl.this.billDctRevService.pass(false, phoneCode,
							location, new String[] { billId });
					if (stats.getAffectedRows() == 0) {
						throw new UnCheckMsgException("������������");
					}
				}
			}
		}, new int[0]);

		return "";
	}

	public void uploadInvoices(String dctId, String attInvoicesJson) {
		CbDct dct = (CbDct) this.cbDctService.selectByKey(dctId);
		CbRec rec = (CbRec) this.cbRecService.selectByKey(dct.getBillId());
		Bill<CbDct> bill = new Bill();
		bill.setRec(rec);
		bill.setSource(dct);
		BillEvent<CbDct> event = new BillEvent(bill);
		event.setValue("attInvoices", attInvoicesJson);
		event.setValue("invType", "4");
		event.setValue("bizId", ((CbDct) bill.getSource()).getDctId());
		event.setValue("dfrState", "2");
		event.setValue("uploadDate", SysDateUtil.getSystemDate());
		Observable<BillEvent<CbDct>> observers = Observable.just(event);
		observers.subscribe(this.billAttSubscriber);
		observers.subscribe(this.billInvoiceDfrUploadUpdateSubscriber);
		observers.subscribe(this.billInvoiceDeferedUploadMsgSubcriber);
	}

	private void dct(Bill<CbDct> bill, String attInvoicesJson, String contractFileIds) {
		BillEvent<CbDct> event = new BillEvent(bill);
		CbOpt opt = new CbOpt();
		opt.setLimDate(((CbDct) bill.getSource()).getDctDate());
		opt.setCurState("S005");
		opt.setOptCode("E301");
		opt.setRemark("��������");

		event.setOperation(opt);

		event.setValue("bizId", ((CbDct) bill.getSource()).getDctId());

		event.setValue("attInvoices", attInvoicesJson);
		event.setValue("contractFileIds", contractFileIds);
		event.setValue("invType", "4");
		event.setValue("quotaOptType", "qt_blk");
		((CbDct) bill.getSource()).setDctQtOpt("0");

		Observable<BillEvent<CbDct>> observers = Observable.just(event);
		observers.subscribe(this.billOptSubscriber);
		observers.subscribe(this.billSeeFeeContractSponsorSubscriber);
		observers.subscribe(this.billDctQtSubscriber);
		observers.subscribe(this.valRetBizSaveSubscriber);
		observers.subscribe(this.billDctCpnSubscriber);
		observers.subscribe(this.billDctSubscriber);
		observers.subscribe(this.billMoveSubscriber);
		observers.subscribe(this.billAttSubscriber);
		observers.subscribe(this.billInvoiceDfrUploadSaveSubscriber);

		observers.subscribe(this.billDctMsgSubscriber);
		observers.subscribe(this.contractSponsorSubscriber);
	}

	private void splitDct(CbRec record, List<Bill<CbDct>> bills, String attInvoicesJson, String contractFileIds) {
		Bill<CbDct> prnt = new Bill();
		prnt.setRec(record);
		BillSplitEvent<CbDct> event = new BillSplitEvent(prnt);
		event.setChildren(bills);

		CbOpt opt = new CbOpt();
		opt.setLimDate(((CbDct) ((Bill) bills.get(0)).getSource()).getDctDate());
		opt.setCurState("S005");
		opt.setOptCode("E301");
		opt.setRemark("��������");

		event.setOperation(opt);

		event.setValue("attInvoices", attInvoicesJson);
		event.setValue("contractFileIds", contractFileIds);
		event.setValue("invType", "4");

		Observable<BillSplitEvent<CbDct>> observers = Observable.just(event);
		observers.subscribe(this.billDctCpnSubscriber);
		observers.subscribe(this.valRetBizSaveSubscriber);
		observers.subscribe(this.billDctPrntSubscriber);
		observers.subscribe(this.billDctChdSubscriber);

		observers.subscribe(this.billSplitDctMsgSubscriber);
	}
}
